package cn.alise.controller.common;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.alise.consts.BaseConsts;
import cn.alise.enums.EnumClass;
import cn.alise.qdp.model.user.User;
import cn.alise.util.JSONResult;

import com.alibaba.fastjson.JSONArray;


/**
 * ClassName:BaseController <br/>
 * Description: 公共控制类，所有的控制类都要继承此类 <br/>
 * Date: 2014年11月20日 上午11:30:14 <br/>
 *
 * @author 焦少平
 * @version 1.0
 * @since JDK 1.7
 * @see
 */	

public class BaseController implements Serializable {
	/**	
	 * 日志对象
	 */
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	/**
	 * 序列号
	 */
	private static final long serialVersionUID = -8871338859087443082L;
	
	/**
	 * <p>
	 * getPrintWriter:将对象传到前台 <br/>
	 * 适用条件：AJAX请求<br/>
	 * 执行流程：AJAX调用的方法里调用该方法<br/>
	 * 使用方法：传递response和object参数<br/>
	 * 注意事项:只有需要向前台传递参数的方法里才可以调用该方法<br/>
	 * </p>
	 *
	 * @author:焦少平 Date: 2014年11月9日 下午7:11:05
	 * @param response 响应
	 * @param object 对象
	 * @since JDK 1.7
	 */
	public void getPrintWriter(HttpServletResponse response, Object object) {
		response.setHeader("Content-type", "text/html;charset=UTF-8");
		response.setCharacterEncoding("UTF-8");
		
		PrintWriter out = null;
		try {
			// 得到输出流
			out = response.getWriter();
			out.print(object);
		} catch (IOException e) {
			logger.error("ajax返回页面信息报错，原因：" + e.getMessage(), e);
		} finally {
			if (null != out) {
				out.flush();
				out.close();
			}
		}
	}
	
	/**
	 * <p>
	 * getPrintWriter:将对象传到前台 <br/>
	 * 适用条件：AJAX请求<br/>
	 * 执行流程：AJAX调用的方法里调用该方法<br/>
	 * 使用方法：传递response和object参数<br/>
	 * 注意事项:只有需要向前台传递参数的方法里才可以调用该方法<br/>
	 * </p>
	 *
	 * @author:焦少平 Date: 2014年11月9日 下午7:11:05
	 * @param response 响应
	 * @param object 对象
	 * @since JDK 1.7
	 */
	public void getPrintWriter(HttpServletResponse response, JSONResult object) {
		response.setHeader("Content-type", "text/html;charset=UTF-8");
		response.setCharacterEncoding("UTF-8");
		
		PrintWriter out = null;
		try {
			// 得到输出流
			out = response.getWriter();
			out.print(JSONArray.toJSONString(object));
		} catch (IOException e) {
			logger.error("ajax返回页面信息报错，原因：" + e.getMessage(), e);
		} finally {
			if (null != out) {
				out.flush();
				out.close();
			}
		}
	}
	
	/**
	 * <p>
	 * getPrintWriter:将对象传到前台 <br/>
	 * 适用条件：AJAX请求<br/>
	 * 执行流程：AJAX调用的方法里调用该方法<br/>
	 * 使用方法：传递response和JSONResult对象<br/>
	 * 注意事项:只有需要向前台传递参数的方法里才可以调用该方法<br/>
	 * </p>
	 *
	 * @author:Chunjie He Date: 2014年11月9日 下午7:11:05
	 * @param response 响应
	 * @param code 错误编码
	 * @param error 错误描述
	 * @since JDK 1.7
	 */
	public void writer(HttpServletResponse response, String code, String error) {
		this.getPrintWriter(response, new JSONResult(code, error));
	}
	
	/**
	 * <p>
	 * getPrintWriter:将对象传到前台 <br/>
	 * 适用条件：AJAX请求<br/>
	 * 执行流程：AJAX调用的方法里调用该方法<br/>
	 * 使用方法：传递response和JSONResult对象<br/>
	 * 注意事项:只有需要向前台传递参数的方法里才可以调用该方法<br/>
	 * </p>
	 * @author:Chunjie He Date: 2014年11月9日 下午7:11:05
	 * @param response 响应
	 * @param data 返回的数据
	 * @param message 描述
	 * @since JDK 1.7
	 */
	public void writer(HttpServletResponse response, Object data, String message) {
		this.getPrintWriter(response, new JSONResult(0, data, message));
	}
	
	public void writer(HttpServletResponse response, String message) {
		this.getPrintWriter(response, new JSONResult(message));
	}
	
	/**
	 * <p>
	 * getPrintWriter:将对象传到前台 <br/>
	 * 适用条件：AJAX请求<br/>
	 * 执行流程：AJAX调用的方法里调用该方法<br/>
	 * 使用方法：传递response和JSONResult对象<br/>
	 * 注意事项:只有需要向前台传递参数的方法里才可以调用该方法<br/>
	 * </p>
	 * 
	 * @author:Chunjie He Date: 2014年11月9日 下午7:11:05
	 * @param response 响应
	 * @param status 状态编号
	 * @param code 错误编码
	 * @param errorMsg 错误信息
	 * @since JDK 1.7
	 */
	public void writer(HttpServletResponse response, int status, String code, String errorMsg) {
		this.getPrintWriter(response, new JSONResult(status, code, errorMsg));
	}

	/**
	 * 获取session对象
	 * @return
	 */
	public HttpSession getSession() {
		HttpSession session = null; 
		
		try { 
		    session = getRequest().getSession(); 
		} catch (Exception e) {
			logger.error("获取Session对象报错，原因：" + e.getMessage(), e);
		}
		
		return session; 
	} 

	/**
	 * 获取request对象
	 * @return
	 */
	public HttpServletRequest getRequest() { 
		ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 
		return attrs.getRequest(); 
	}
	
	/**
	 * 从session中将对象清空
	 * @param key
	 */
	public void removeSessionValue(String key) {
		this.getSession().removeAttribute(key);
	}
	
	/**
	 * 从request对象中获取值
	 * @param key
	 */
	public Object getRequestValue(String key) {
		return this.getRequest().getAttribute(key);
	}
	
	/**
	 * 向session中添加值
	 * @param key
	 * @param value
	 */
	public void setSessionValue(String key, Object value) {
		this.getSession().setAttribute(key, value);
	}
	
	/**
	 * 从session对象中获取值
	 * @param key
	 * @return
	 */
	public Object getSesionValue(String key) {
		return this.getSession().getAttribute(key);
	}
	
	/**
	 * 获取异常信息
	 * @param action
	 * @param e
	 * @return
	 * @author zhuyf
	 */
	protected String getExceptionMessage(String action, Exception e) {
		Throwable source = getSqlException(e);
		return action + " -> " + e.getMessage() + (source != null ? " --> DB_ERROR:" + source.getMessage() : "");
	}
	
	/**
	 * 获取IP地址
	 * @return
	 */
	public String getIpAddr() {
		HttpServletRequest request = this.getRequest();
		
        String ip = request.getHeader("x-forwarded-for"); 
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP"); 
        }
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP"); 
        }
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr(); 
        }
        
        return ip; 
    } 

	/**
	 * 获取sql异常
	 * @param e
	 * @return
	 * @author zhuyf
	 */
	protected Throwable getSqlException(Exception e) {
		Throwable source = e;
		// 简单查询异常的8层Cause
		for (int i = 0; i < 8; i++) {
			if (source.getCause() == null) {
				return null;
			} else {
				source = source.getCause();
			}
			
			if (source.getClass().toString().equals(SQLException.class.toString())) {
				return source.getCause();
			}
		}
		return source;
	}
	
	
	/**
	 * 设置调用接口的参数
	 * @param params 参数名以逗号分隔
	 * @param obj 实体对象
	 * @return
	 */
	protected Map<String,String> setRequestParams(String params,Object obj) {
		Map<String, String> paramsMap = new HashMap<String, String>();
		if(obj == null) return paramsMap;
		if(StringUtils.isBlank(params)) return paramsMap;
		String[] paramArray = params.split(",");
		for(String paramName:paramArray) {
			try {
				Field field = obj.getClass().getDeclaredField(paramName);
				field.setAccessible(true);
				Object value = field.get(obj);
				if(value == null) continue;
				paramsMap.put(paramName, value.toString());
			} catch (Exception e) {
				continue;
			}
		}
		return paramsMap;
	}
	
	/**
	 * 从session中获取账号对象
	 * @return
	 */
	public User getAccountFromSession() {
		return (User) this.getSesionValue(BaseConsts.IUser.USER_SESSION_KEY);
	}
	
	/**
	 * 将Object对象转换为指定类型的对象
	 * @param data
	 * @param clazz
	 * @return 
	 * @return 
	 * @return
	 */
	protected <T> T transfObject(Object data, Class<T> clazz) {
		return JSONArray.parseObject(data.toString(), clazz);
	}
	
	/**
	 * 将Object对象转换为指定类型的List对象
	 * @param data
	 * @param clazz
	 * @return 
	 * @return 
	 * @return
	 */
	protected <T> List<T> transfArray(Object data, Class<T> clazz) {
		return JSONArray.parseArray(data.toString(), clazz);
	}
	
	/**
	 * 组装成功的json结果集
	 * @param data
	 */
	protected JSONResult gainSuccessJsonData(Object Data) {
		JSONResult result = new JSONResult();
		result.setData(Data);
		result.setStatus(EnumClass.ResultCodeType.SUCCESS.getKey());
		result.setMessage(EnumClass.ResultCodeType.SUCCESS.getValue());
		return result;
	}
	
	/**
	 * 组装成功的json失败结果集
	 * @param data
	 */
	protected JSONResult gainFailJsonData(String msg) {
		JSONResult result = new JSONResult();
		result.setStatus(EnumClass.ResultCodeType.FAIL.getKey());
		result.setMessage(msg);
		return result;
	}
}
